跳到主要内容

[toc]

awk BEGIN模式、END模式

1.BEGIN模式

BEGIN模式在awk程序执行后,但尚未执行处理动作之前需要做的工作(定义变量)

作用一 修改标题

//文件a.txt内容如下
101,abc,CEO
102,def,CTO
103,qaz,COO

//默认打印
[root@7-test1 ~]# awk '{print}' a.txt
101,abc,CEO
102,def,CTO
103,qaz,COO

//打印标题,注意ID、name必须用双引号
[root@7-test1 ~]# awk 'BEGIN{print "ID","name","position"}{print}' a.txt
ID name position
101,abc,CEO
102,def,CTO
103,qaz,COO

作用二 做运算

示例1:计算1到100的和

[root@7-test1 ~]# awk 'BEGIN{for(i=1;i<=100;i++) sum+=i;print sum}'
5050

示例2:普通计算

[root@7-test1 ~]# awk 'BEGIN{print 3+3}'
6
[root@7-test1 ~]# awk 'BEGIN{print 3*3}'
9
[root@7-test1 ~]# awk 'BEGIN{print 3-3}'
0
[root@7-test1 ~]# awk 'BEGIN{print 3**3}'
27
[root@7-test1 ~]# awk 'BEGIN{print 3%3}'
0
[root@7-test1 ~]# awk 'BEGIN{print 3/3}'
1

作用三 修改awk内置变量

record 字段

separator 分隔符

变量名对应单词含义
FSfield separator字段分隔符,默认空格或tab
OFSoutput field separator输出分隔符,默认空格
RSrecord separator记录分隔符,默认换行符\n
ORSoutput record separator输出记录分隔符

FS 指定字段分隔符

//passwd.txt文件内容如下
[root@7-test1 ~]# cat passwd.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

示例1:以冒号为分隔符,打印文件第一列
//-F写法
[root@7-test1 ~]# awk -F: '{print $1}' passwd.txt
root
bin
daemon

//BEGIN {FS}写法
[root@7-test1 ~]# awk 'BEGIN{FS=":"}{print $1}' passwd.txt
root
bin
daemon

OFS 指定输出分隔符

//文件内容如下
[root@7-test1 ~]# cat a.txt
1 2 3

示例1:打印文件第一列和第三列,以冒号为分隔符
//-v OFS写法
[root@7-test1 ~]# awk -v OFS=: '{print $1,$3}' a.txt
1:3

//BEGIN {OFS}写法
[root@7-test1 ~]# awk 'BEGIN{OFS=":"}{print $1,$3}' a.txt
1:3


⚠️⚠️⚠️注意:!!!
-v OFS写法的一个坑:当print $0的时候,-v OFS会不生效

//正确输出应该为1:2:3
[root@7-test1 ~]# awk -v OFS=: '{print $0}' a.txt
1 2 3

解决方法
print$0前加一个$1=$1
[root@7-test1 ~]# awk -v OFS=: '{$1=$1;print $0}' a.txt
1:2:3

RS 指定记录分隔符,即指定以什么为分隔符,默认为\n

//文件内容
文件默认以换行为记录分隔符
[root@7-test1 ~]# cat passwd.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

示例1:将文件的记录分隔符指定为/,即指定文件以/为换行符
//-v RS写法
[root@7-test1 ~]# awk -v RS=/ '{print $0}' passwd.txt
root:x:0:0:root:
root:
bin
bash
bin:x:1:1:bin:
bin:
sbin
nologin

//BEGIN {RS}写法
[root@7-test1 ~]# awk 'BEGIN{RS="/"}{print $0}' passwd.txt
root:x:0:0:root:
root:
bin
bash
bin:x:1:1:bin:
bin:
sbin
nologin

ORS 指定输出记录分隔符

//文件内容
[root@7-test1 ~]# cat a.txt
1
2
3

示例1:将文件的输出记录分隔符指定为/
//-v ORS写法
[root@7-test1 ~]# awk -v ORS="A" '{print $0}' a.txt
1A2A3A

//BEGIN {ORS}写法
[root@7-test1 ~]# awk 'BEGIN{ORS="A"}{print $0}' a.txt
1A2A3A

扩展-awk命令行参数

ARGC是命令行参数数量

ARGV是将命令行参数存到数组,元素由ARGC指定,数组下标从0开始

ARGC

[root@test1 ~]# awk 'BEGIN{print ARGC}'
1
[root@test1 ~]# awk 'BEGIN{print ARGC}' 1 2
3

ARGV

[root@test1 ~]# awk 'BEGIN{print ARGV[0]}' 1 2
awk
[root@test1 ~]# awk 'BEGIN{print ARGV[1]}' 1 2
1
[root@test1 ~]# awk 'BEGIN{print ARGV[2]}' 1 2
2

2.END模式

END模式在awk读取完文件之后执行,主要作用为显示计算结果

作用 显示计算结果

示例1:统计/etc/passwd文件中前10行非登陆shell的个数

//文件内容
[root@7-test1 awk]# head -10 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

//统计文件中非登陆shell的个数,即统计/sbin/nologin的个数
[root@7-test1 awk]# head -10 /etc/passwd|awk '/nologin/{i++}END{print i}'
6

示例2:统计/etc/services中空行数量

[root@7-test1 awk]# awk '/^$/{i++}END{print i}' /etc/services
17

示例3:统计nginx访问日志中访问量前10的IP

[root@7-test1 ~]# awk '{a[$1]++}END{for(i in a) print a[i],i}' /var/log/nginx/access.log|sort -nr|head
275 109.98.109.101
262 146.196.97.242
210 47.52.155.218
152 142.234.200.81
75 72.211.58.142
10 120.25.208.128
7 42.236.10.84
6 42.236.10.92
3 5.188.210.12
3 42.236.10.75